package templateExecel2.extract;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import templateExecel2.utils.PoiUtils;

import java.util.List;
import java.util.Map;

/*

 */

//模板行的包装
public class TemplateRow {

    //如果行不为null则该字段不为null
    private WorkRow extractRow;

    //私有构造器
    private TemplateRow() {

    }

    //列数必须完全相等
    public static final int COL_NUMBER_MATCHING_MODE_EQUALS = 1;

    //使用交集匹配
    public static final int COL_NUMBER_MATCHING_MODE_INTERSECTION = 2;

    //完整保留模板行
    public static final int COL_NUMBER_MATCHING_MODE_TEMPLATE_FULL = 3;

    private int colNumberMatchingMode = COL_NUMBER_MATCHING_MODE_EQUALS;

    public static TemplateRow compile(XSSFRow xssfRow, Map<Integer, Merge> mergeMap, Map<String, List<ValueHolder>> colValueMap, int colModel) {

        if (xssfRow != null) {
            TemplateRow row = new TemplateRow();
            short firstCellNum = xssfRow.getFirstCellNum();
            short lastCellNum = xssfRow.getLastCellNum();

            WorkRow extractRow = new WorkRow(colValueMap);
            row.extractRow = extractRow;
            row.colNumberMatchingMode = colModel;
            extractRow.setFirstCol(firstCellNum);
            extractRow.setLastCol(lastCellNum);

            for (int i = firstCellNum; i < lastCellNum; i++) {

                Merge merge = mergeMap.get(i);
                if (merge == null) {
                    merge = Merge.get(1, 1);
                }

                XSSFCell cell = xssfRow.getCell(i);

                if (cell == null) {
                    extractRow.compile(i, null, merge);
                } else {
                    extractRow.compile(i, PoiUtils.readCell(cell), merge);
                }

            }

            return row;
        } else {
            return null;
        }


    }

    //是否正在搜索匹配规则的行
    private boolean finding = true;


    //提取一行,如果能够提取到结果就返回提取到的Map,否则返回null
    public boolean extract(XSSFRow xssfRow, Map<Integer, Merge> mergeMap) {

        short firstCellNum = xssfRow.getFirstCellNum();
        short lastCellNum = xssfRow.getLastCellNum();

        /*
            初始时模板行处于搜索状态,直到找到符合条件的时候终止搜索状态
         */
        if (this.extractRow.getFirstCol() != firstCellNum || this.extractRow.getLastCol() != lastCellNum) {
            if (colNumberMatchingMode == COL_NUMBER_MATCHING_MODE_EQUALS) {
                return finding;
            } else if (colNumberMatchingMode==COL_NUMBER_MATCHING_MODE_INTERSECTION) {
                if (this.extractRow.getLastCol() < firstCellNum) {
                    return finding;
                }

                if (lastCellNum < this.extractRow.getFirstCol()) {
                    return finding;
                }


                //TODO 匹配位置取交集
                if (firstCellNum < this.extractRow.getFirstCol()) {
                    firstCellNum = (short) this.extractRow.getFirstCol();
                }

                if (lastCellNum > this.extractRow.getLastCol()) {
                    lastCellNum = (short) this.extractRow.getLastCol();
                }

            } else if (colNumberMatchingMode == COL_NUMBER_MATCHING_MODE_TEMPLATE_FULL) {//完整保留模板行
                if (firstCellNum > this.extractRow.getFirstCol() || lastCellNum < this.extractRow.getLastCol()) {
                    return finding;
                }
                firstCellNum = (short) this.extractRow.getFirstCol();
                lastCellNum = (short) this.extractRow.getLastCol();

            }
        }

        for (int i = firstCellNum; i < lastCellNum; i++) {
            Merge merge = mergeMap.get(i);
            if (merge == null) {
                merge = Merge.get(1, 1);
            }

            Object v = null;
            XSSFCell cell = xssfRow.getCell(i);
            if (cell != null) {
                v = PoiUtils.readCell(cell);
            }

            if (!this.extractRow.extract(i, v, merge)) {
                return finding;
            }

        }

        //已经找到符合条件的位置
        finding = false;

        //返回本行中提取的结果
        return true;
    }

}
